import sys
import os
import cv2
import numpy as np
from PIL import Image
from typing import Union
import open3d as o3d
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import argparse

def cut(image:Image, padding):
    w = image.width
    h = image.height
    if 0 <= max(padding) <= 1:
        # is normal
        left = w *padding[0]
        top = w *padding[1]
        right = w * (1 - padding[2])
        bottom = h * (1 - padding[3])
    else:
        left = padding[0]
        top = padding[1]
        right = w - padding[2]
        bottom = h - padding[3]
    return image.crop ((left, top, right, bottom))


def resize(image:Image, scale, to_width, to_height, to_min, to_max):
    w = image.width
    h = image.height
    rateX = None
    rateY = None
    if scale is not None:
        rateX = scale
    elif to_min is not None:
        rateX = to_min / min(w,h)
    elif to_max is not None:
        rateX = to_max / max(w,h)
    if to_width is not None:
        rateX = to_width / w
    if to_height is not None:
        rateY = to_height / h
    if rateX is None and rateY is None:
        rateX = 1.0
        rateY = 1.0
    elif rateX is None:
        rateX = rateY
    elif rateY is None:
        rateY = rateX
    return image.resize((int(rateX*w),int(rateY*h)))

def crop (image:Image, region):
    w = image.width
    h = image.height
    offset_x = 0
    offset_y = 0
    
    
    if 0 < max(region) < 1:
        # is normal
        offset_x = int(w * region[0])
        offset_y = int(h * region[1])
        new_w = int(w * region[2])
        new_h = int(h * region[3])
    else:
        offset_x = region[0]
        offset_y = region[1]
        new_w = region[2]
        new_h = region[3]

    left = offset_x
    top = offset_y
    right = left + new_w
    bottom = top + new_h
    return image.crop((left, top, right, bottom))


def main():
    # 创建 ArgumentParser 对象
    parser = argparse.ArgumentParser(description="mask show")
    parser.add_argument("filepath", help="文件的路径")
    parser.add_argument("-o", "--output", type=str, help="set crop  output path")
    parser.add_argument("-p", "--padding", type=float, nargs='+', help="set cut padding, [left,top,right,bottom]")
    parser.add_argument("--scale", type=float, help="set image scale to rate")
    parser.add_argument("--to_width", type=float, help="set image scale to width value")
    parser.add_argument("--to_height", type=float, help="set image scale to height value")
    parser.add_argument("--to_min", type=float, help="set image scale to min value")
    parser.add_argument("--to_max", type=float, help="set image scale to max value")
    parser.add_argument("-r", "--region", type=float, nargs='+', help="set crop region, [x,y,width,heigh]")
    parser.add_argument("-a", "--anchor", type=float, nargs='+', default=None, help="set crop object anchor, [x,y]")
    parser.add_argument("-f", "--half", type=str, choices=('left','right','up','down'), default=None, help="set half crop option")
    
    args = parser.parse_args()
    suffixes = ['jpg', 'jpeg', 'png']
    image_paths = []
    if os.path.isdir(args.filepath):
        image_paths = [os.path.join(args.filepath, f) for f in os.listdir(args.filepath) if f.endswith(tuple(suffixes))]
    else:
        image_paths.append(args.filepath)

    for path in image_paths:
        image = Image.open(path)
        # image = image.convert(image.mode)
        # padding
        if args.padding is not None:
            image = cut(image, args.padding)
        # resize
        if not all(v is None for v in (args.scale, args.to_width, args.to_height, args.to_min, args.to_max)):
            image = resize(image, args.scale, args.to_width, args.to_height, args.to_min, args.to_max)
        
        if args.half is not None:
            # half crop
            w = image.width
            h = image.height
            if args.half == 'left':
                image = image.crop((0, 0, w//2, h))
            elif args.half == 'right':
                image = image.crop((w//2, 0, w, h))
            elif args.half == 'up':
                image = image.crop((0, 0, w, h//2))
            elif args.half == 'down':
                image = image.crop((0, h//2, w, h))
        elif args.region is not None:
            # crop 
            image = crop(image, args.region)
        # save
        if args.output is None:
            name = os.path.splitext(path)
            output_path = os.path.join(os.path.dirname(path),  name[0] + '_crop' + name[1])
        else:
            output_path = os.path.join(args.output, os.path.basename(path)) if os.path.isdir(args.output) else args.output
        print(f'crop saving {output_path}')
        image.save(output_path)


# 使用示例
if __name__ == "__main__":
    main()